/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mysimpatico.sqlwrapper.vendoradapters;

import com.mysimpatico.sqlwrapper.Column;
import com.mysimpatico.sqlwrapper.SqlWrapper;
import com.mysimpatico.sqlwrapper.SqlWrapper.ConflictResolution;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;

/**
 *
 * @author simpatico
 */
public abstract class VendorAdapter {

     /**
     * SQLite seems to not support create=false syntax. But what does it support?
     * @param create
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public Connection connect(final boolean inMemory, final String dbName, final boolean createIfNew) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException {
        Class.forName(getDriverName());
        final Connection con = DriverManager.getConnection(getConnectionURLPrefix() + (inMemory ? "memory:" : "") + dbName + ";create=" + createIfNew);
        return con;
    }

    public abstract String getPrimaryKeyDeclaration();

    protected abstract String getDriverName();

    protected abstract String getConnectionURLPrefix();

    public String getPrimaryKey(final Column[] primaryKeys){
        return "PRIMARY KEY(" + SqlWrapper.joinColumns(primaryKeys, SqlWrapper.QueryType.FOREIGN) + ")";
    }

    public static long millisTestOffset = 0;

    public Column getRidColumn(){
        return Column.createIntColumn(SqlWrapper.rid);
    }

    public String getDate(){
        return "(SELECT DATE('now'," + millisTestOffset / 1000 + "))";
    }

    public String escapeString(final String string) {
        if(string == null) throw new RuntimeException("passed null string to escape.");
        final StringBuilder result = new StringBuilder();

        final StringCharacterIterator iterator = new StringCharacterIterator(string);
        char character = iterator.current();
        while (character != CharacterIterator.DONE) {
            if (character == '\\') {
                result.append("\\\\");
            } else if (character == '\'') {
                result.append("''");
            } else {
                result.append(character);
            }
            character = iterator.next();
        }
        return "'" + result.toString() + "'";
    }

    public String getOnConflict(final ConflictResolution res, final boolean update){
        return (update) ? "OR " + res : "ON CONFLICT " + res;
    }
}
